package com.xiaolin.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xiaolin.admin.constants.FlagConstant;
import com.xiaolin.admin.constants.OptConstant;
import com.xiaolin.admin.exception.ServiceException;
import com.xiaolin.admin.mapper.SysRoleMapper;
import com.xiaolin.admin.mapper.SysRoleMenuMapper;
import com.xiaolin.admin.mapper.SysRoleOrgMapper;
import com.xiaolin.admin.mapper.SysUserRoleMapper;
import com.xiaolin.admin.model.dto.CurrentUser;
import com.xiaolin.admin.model.entity.*;
import com.xiaolin.admin.service.SysRoleMenuService;
import com.xiaolin.admin.service.SysRoleOrgService;
import com.xiaolin.admin.service.SysRoleService;
import com.xiaolin.admin.service.SysUserRoleService;
import com.xiaolin.admin.utils.ContextUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色表 服务实现类
 * </p>
 *
 * @author xiaolin
 * @since 2024-07-29
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {

    @Autowired
    private SysRoleMapper roleMapper;

    @Autowired
    private SysUserRoleService userRoleService;

    @Autowired
    private SysRoleMenuService roleMenuService;

    @Autowired
    private SysRoleOrgService roleOrgService;

    @Autowired
    private SysUserRoleMapper userRoleMapper;

    @Autowired
    private SysRoleMenuMapper roleMenuMapper;

    @Autowired
    private SysRoleOrgMapper roleOrgMapper;

    @Autowired
    private ContextUtil contextUtil;

    @Override
    public List<SysRole> getList(SysRole role) {
        return roleMapper.getRoleList(role);
    }

    @Override
    public PageInfo<SysRole> getRolePage(Integer page, Integer pageSize, SysRole role) {
        PageHelper.startPage(page, pageSize);
        List<SysRole> roleList = roleMapper.getRoleList(role);
        return new PageInfo<>(roleList);
    }

    /**
     * 校验角色唯一性
     *
     * @param role
     * @return
     */
    @Override
    public void checkUnique(SysRole role) {
        long count = roleMapper.selectCount(new LambdaQueryWrapper<SysRole>()
                .and(qr -> qr.eq(SysRole::getRoleName, role.getRoleName()).or().eq(SysRole::getRoleCode, role.getRoleCode()))
                .ne(Objects.nonNull(role.getId()), SysRole::getId, role.getId()));
        if (count > 0) {
            ServiceException.error("角色名称或角色码重复了");
        }
    }

    @Override
    public void checkUserRelation(Integer roleId) {
        // 校验与用户关联关系
        long count = userRoleMapper.selectCount(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getRoleId, roleId));
        if (count > 0) {
            ServiceException.error("该角色关联了用户，无法删除");
        }
    }

    @Override
    public void deleteMenuRelation(Integer roleId) {
        CurrentUser user = contextUtil.getCurrentUser();
        roleMenuMapper.update(new SysRoleMenu(), new UpdateWrapper<SysRoleMenu>().lambda()
                .set(SysRoleMenu::getFlag, FlagConstant.DELETED)
                .set(SysRoleMenu::getUpdator, user.getId())
                .eq(SysRoleMenu::getRoleId, roleId));
    }

    @Override
    public void deleteOrgRelation(Integer roleId) {
        CurrentUser user = contextUtil.getCurrentUser();
        roleOrgMapper.update(new SysRoleOrg(), new UpdateWrapper<SysRoleOrg>().lambda()
                .set(SysRoleOrg::getFlag, FlagConstant.DELETED)
                .set(SysRoleOrg::getUpdator, user.getId())
                .eq(SysRoleOrg::getRoleId, roleId));
    }

    @Override
    public boolean addRole(SysRole role) {
        CurrentUser user = contextUtil.getCurrentUser();
        // 校验角色唯一性
        checkUnique(role);
        role.setCreator(user.getId());
        role.setUpdator(user.getId());
        roleMapper.insert(role);
        return true;
    }

    @Override
    public SysRole getRole(Integer id) {
        return roleMapper.selectById(id);
    }

    @Override
    public boolean updateRole(SysRole role) {
        // 校验角色唯一性
        checkUnique(role);
        roleMapper.updateById(role);
        return true;
    }

    @Override
    public boolean status(Integer id, String status) {
        CurrentUser user = contextUtil.getCurrentUser();
        roleMapper.update(new SysRole(), new UpdateWrapper<SysRole>().lambda()
                .set(SysRole::getAvailable, status)
                .set(SysRole::getUpdator, user.getId())
                .eq(SysRole::getId, id));
        return true;
    }

    @Override
    public boolean deleteRole(Integer id) {
        // 校验角色与用户是否关联
        checkUserRelation(id);
        // 删除角色与菜单的关联关系
        deleteMenuRelation(id);
        // 删除角色与部门的关联关系
        deleteOrgRelation(id);
        roleMapper.deleteById(id);
        return true;
    }

    @Override
    public boolean configRoleForUsers(Integer roleId, String optType, List<Integer> userIds) {
        if (CollectionUtils.isEmpty(userIds)) {
            ServiceException.error("请选择要绑定或解绑的用户");
        }
        CurrentUser user = contextUtil.getCurrentUser();
        if (OptConstant.ADD.equals(optType)) {
            // 用户绑定角色
            List<SysUserRole> userRoles = userIds.stream().map(userId -> {
                SysUserRole userRole = new SysUserRole();
                userRole.setUserId(userId);
                userRole.setRoleId(roleId);
                userRole.setCreator(user.getId());
                userRole.setUpdator(user.getId());
                return userRole;
            }).collect(Collectors.toList());
            userRoleService.saveBatch(userRoles);
            return true;
        } else if (OptConstant.UPDATE.equals(optType)) {
            // 用户解绑角色
            userRoleService.update(new UpdateWrapper<SysUserRole>().lambda()
                    .set(SysUserRole::getFlag, FlagConstant.DELETED)
                    .set(SysUserRole::getUpdator, user.getId())
                    .eq(SysUserRole::getRoleId, roleId).in(SysUserRole::getUserId, userIds));
            return true;
        } else {
            ServiceException.error("非法操作");
            return false;
        }
    }

    @Override
    public List<Integer> getBoundUsers(Integer roleId) {
        List<SysUserRole> userRoles = userRoleService.list(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getRoleId, roleId));
        return userRoles.stream().map(SysUserRole::getUserId).collect(Collectors.toList());
    }

    @Override
    public boolean configMenuForRole(Integer roleId, List<Integer> menuIds) {
        CurrentUser user = contextUtil.getCurrentUser();
        // 删除角色已绑定的模块
        roleMenuService.update(new UpdateWrapper<SysRoleMenu>().lambda()
                .set(SysRoleMenu::getFlag, FlagConstant.DELETED)
                .set(SysRoleMenu::getUpdator, user.getId())
                .eq(SysRoleMenu::getRoleId, roleId));
        // 新增要绑定的模块
        List<SysRoleMenu> roleMenus = menuIds.stream().map(menuId -> {
            SysRoleMenu roleMenu = new SysRoleMenu();
            roleMenu.setRoleId(roleId);
            roleMenu.setMenuId(menuId);
            roleMenu.setCreator(user.getId());
            roleMenu.setUpdator(user.getId());
            return roleMenu;
        }).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(roleMenus)) {
            roleMenuService.saveBatch(roleMenus);
        }
        return true;
    }

    @Override
    public List<Integer> getBoundMenus(Integer roleId) {
        List<SysRoleMenu> roleMenus = roleMenuService.list(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, roleId));
        return roleMenus.stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList());
    }

    @Override
    public boolean configOrgForRole(Integer roleId, List<Integer> orgIds) {
        CurrentUser user = contextUtil.getCurrentUser();
        // 删除角色已绑定的模块
        roleOrgService.update(new UpdateWrapper<SysRoleOrg>().lambda()
                .set(SysRoleOrg::getFlag, FlagConstant.DELETED)
                .set(SysRoleOrg::getUpdator, user.getId())
                .eq(SysRoleOrg::getRoleId, roleId));
        // 新增要绑定的模块
        List<SysRoleOrg> roleOrgs = orgIds.stream().map(orgId -> {
            SysRoleOrg roleOrg = new SysRoleOrg();
            roleOrg.setRoleId(roleId);
            roleOrg.setOrgId(orgId);
            roleOrg.setCreator(user.getId());
            roleOrg.setUpdator(user.getId());
            return roleOrg;
        }).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(roleOrgs)) {
            roleOrgService.saveBatch(roleOrgs);
        }
        return true;
    }

    @Override
    public List<Integer> getBoundOrgs(Integer roleId) {
        List<SysRoleOrg> roleOrgs = roleOrgService.list(new LambdaQueryWrapper<SysRoleOrg>().eq(SysRoleOrg::getRoleId, roleId));
        return roleOrgs.stream().map(SysRoleOrg::getOrgId).collect(Collectors.toList());
    }

    /**
     * 获取用户角色
     *
     * @return
     */
    @Override
    public List<String> getUserRoles() {
        CurrentUser currentUser = contextUtil.getCurrentUser();
        return roleMapper.getUserRoles(currentUser.getId());
    }
}
